package com.evil.application.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evil.application.mapper.ApplicationFilterItemMapper;
import com.evil.application.pojo.dto.view.config.filter.FilterGroupConfigDTO;
import com.evil.application.pojo.entity.ApplicationFilterGroup;
import com.evil.application.pojo.entity.ApplicationFilterItem;
import com.evil.application.service.ApplicationFilterItemService;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.core.util.StreamUtil;
import com.evil.common.family.enums.RCodeEnum;
import com.evil.common.family.enums.SpecialFieldEnum;
import com.evil.common.core.enums.SwitchEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 应用筛选项表
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@Service
@AllArgsConstructor
public class ApplicationFilterItemServiceImpl extends ServiceImpl<ApplicationFilterItemMapper, ApplicationFilterItem> implements ApplicationFilterItemService {

    private final ApplicationLogServiceImpl logService;

    /**
     * 获取筛选组筛选项
     *
     * @param groupIds groupIds
     * @return Map
     */
    @Override
    public Map<Long, List<ApplicationFilterItem>> findItemByGroupIds(Collection<Long> groupIds) {
        return this.baseMapper.findGroupItemsByGroupIds(groupIds);
    }

    /**
     * 获取筛选组下所有筛选项
     *
     * @param filterGroupIds filterGroupIds
     * @return 组项map
     */
    @Override
    public Map<Long, Map<Long, ApplicationFilterItem>> findGroupItemMapByGroupIds(Collection<Long> filterGroupIds) {
        return this.baseMapper.findGroupItemMapByGroupIds(filterGroupIds);
    }

    /**
     * 保存筛选项
     *
     * @param filterGroup       filterGroup
     * @param filterGroupConfig filterGroupConfig
     */
    @Override
    public void saveFilterItem(ApplicationFilterGroup filterGroup, List<FilterGroupConfigDTO> filterGroupConfig) {
        Map<Long, ApplicationFilterItem> filterItemMap = this.baseMapper.findMapByGroupId(filterGroup.getFilterGroupId());

        List<ApplicationFilterItem> modifies = new ArrayList<>();
        List<Long> modifyIds = new ArrayList<>();
        filterGroupConfig.forEach(i -> {
            ApplicationFilterItem item;
            if (Objects.nonNull(i.getFilterItemId())) {
                if (!filterItemMap.containsKey(i.getFilterItemId())) {
                    throw new BusinessException(RCodeEnum.APPLICATION_FILTER_ITEM_NOT_EXIST);
                }
                item = filterItemMap.get(i.getFilterItemId());
                modifyIds.add(item.getFilterItemId());
            } else {
                item = new ApplicationFilterItem();
                item.setEnterpriseId(filterGroup.getEnterpriseId());
                item.setFilterGroupId(filterGroup.getFilterGroupId());
            }
            i.copyProp(item);

            modifies.add(item);
        });

        // 删除
        modifies.addAll(StreamUtil.peekF(filterItemMap.values(), i -> !modifyIds.contains(i.getFilterItemId()), i -> i.setIsDeleted(SwitchEnum.YES.getId())));

        logService.save(this.baseMapper, ApplicationFilterItem::getFilterItemId, modifies);
    }

    /**
     * 复制筛选项
     *
     * @param sourceGroup  sourceGroup
     * @param targetGroup  targetGroup
     * @param updateSource 是否更新源信息
     */
    @Override
    public void copyFilterItem(ApplicationFilterGroup sourceGroup, ApplicationFilterGroup targetGroup, boolean updateSource) {

        Map<Long, ApplicationFilterItem> sourceItemMap = this.baseMapper.findMapByGroupId(sourceGroup.getFilterGroupId());
        Map<Long, ApplicationFilterItem> targetItemMap = this.baseMapper.findMapByGroupId(targetGroup.getFilterGroupId());

        List<Long> modifyIds = new ArrayList<>();
        sourceItemMap.forEach((id, item) -> {
            ApplicationFilterItem copyItem;
            // 需要更新源信息并且对应有值
            if (updateSource && targetItemMap.containsKey(item.getSourceItemId())) {
                copyItem = targetItemMap.get(item.getSourceItemId());
                copyItem.setFilterItemName(item.getFilterItemName());
                copyItem.setDefaultValue(item.getDefaultValue());
                copyItem.setFilterCondition(item.getFilterCondition());
                copyItem.setJudgeSign(item.getJudgeSign());
                copyItem.setOptions(item.getOptions());

                modifyIds.add(item.getSourceItemId());
            } else {
                copyItem = BeanUtil.copyProperties(item, ApplicationFilterItem.class, SpecialFieldEnum.getSpecialFields());
                copyItem.setFilterItemId(null);
                copyItem.setEnterpriseId(targetGroup.getEnterpriseId());
                copyItem.setFilterGroupId(targetGroup.getFilterGroupId());

                // 如果需要更新源信息：新的 需要映射上 复制源ID
                if (updateSource) {
                    copyItem.setSourceItemId(id);
                }
            }

            logService.saveAndCheck(this.baseMapper, ApplicationFilterItem::getFilterItemId, copyItem);

            // 如果需要更新源信息：复制源 需要映射上 新ID
            if (updateSource) {
                item.setSourceItemId(copyItem.getFilterItemId());
                logService.saveAndCheck(this.baseMapper, ApplicationFilterItem::getFilterItemId, item);
            }
        });

        // 删除(备注，如果不需要要更新源信息，则属于完全新复制，即完全删除旧数据)
        List<ApplicationFilterItem> deletedList = StreamUtil.peekF(targetItemMap.values(),
                i -> !modifyIds.contains(i.getFilterItemId()), i -> i.setIsDeleted(SwitchEnum.YES.getId()));
        logService.save(this.baseMapper, ApplicationFilterItem::getFilterItemId, deletedList);
    }

    /**
     * 删除筛选项
     *
     * @param groupIds groupIds
     */
    @Override
    public void deleteFilterItem(Collection<Long> groupIds) {
        List<ApplicationFilterItem> items = StreamUtil.peek(this.baseMapper.findByGroupIds(groupIds), e -> e.setIsDeleted(SwitchEnum.YES.getId()));
        logService.saveAndCheck(this.baseMapper, ApplicationFilterItem::getFilterItemId, items);
    }
}
